#!/usr/bin/env bash
# show_progress -- Shows data flow progress by lines and bytes
# > show_progress input_to    NAME [OPTION...] -- COMMAND [ARG...]
# > show_progress output_from NAME [OPTION...] -- COMMAND [ARG...]
#
# Recognized OPTIONs are:
#  total_bytes=NUM_BYTES
#  total_lines=NUM_LINES
# where NUM_BYTES and NUM_LINES are estimates and can be bash expressions,
# e.g., $(deepdive sql eval "SELECT COUNT(*) FROM ...").
#
# There's a simple environment variable switch to prevent this from
# instrumenting the pipe with progress monitor:
# > export DEEPDIVE_SHOW_PROGRESS=false
# > show_progress ...
##
set -euo pipefail

: ${DEEPDIVE_SHOW_PROGRESS:=true}

[[ $# -gt 0 ]] || usage "$0" "Missing input_to or output_from"
InOut=$1; shift
[[ $# -gt 0 ]] || usage "$0" "Missing NAME"
Name=$1; shift

[[ $# -gt 0 ]] || usage "$0" "Missing COMMAND"
# parse extra options until --
Options=()
while [[ $# -gt 0 && $1 != "--" ]]; do
    Options+=("$1"); shift
done
[[ ${1:-} = "--" ]] || usage "$0" "Missing -- before COMMAND"
shift

# map options to pv flags
PipeViewOpts=()
pv_format="%N %t %b %a (%r)"
[[ ${#Options[@]} -eq 0 ]] || declare -- "${Options[@]}"
: ${total_bytes:=} ${total_lines:=}
# if total size estimate is given show progress bar and ETA
pv_format_bytes=$pv_format; [[ -z $total_bytes ]] || pv_format_bytes+=" %p %e"
pv_format_lines=$pv_format; [[ -z $total_lines ]] || pv_format_lines+=" %p %e"

if $DEEPDIVE_SHOW_PROGRESS && test -t 1 >/dev/tty; then
    # add some default pv(1) options
    PipeViewOpts+=(
        ${Name:+--name "$Name"}
        --cursor
    )
    trap "stty echo <>/dev/tty || true" EXIT # to restore sometimes garbled terminal
    case $InOut in
        input_to) eval '
            pv 2>/dev/tty "${PipeViewOpts[@]}" --format="$pv_format_bytes" '"${total_bytes:+--size="$total_bytes"}"' |
            pv 2>/dev/tty "${PipeViewOpts[@]}" --format="$pv_format_lines" '"${total_lines:+--size="$total_lines"}"' --line-mode |
            "$@"
            ' ;;

        output_from) eval '
            "$@" |
            pv 2>/dev/tty "${PipeViewOpts[@]}" --format="$pv_format_bytes" '"${total_bytes:+--size="$total_bytes"}"' |
            pv 2>/dev/tty "${PipeViewOpts[@]}" --format="$pv_format_lines" '"${total_lines:+--size="$total_lines"}"' --line-mode
            ' ;;

        *)
            trap - EXIT  # no need to mess around with the terminal
            error "$InOut: Cannot show progress, only 'input_to' and 'output_from' are supported"
    esac
else
    # just execute given COMMAND if the file descriptor is not a tty
    exec "$@"
fi
